package com.divemotor.ventarepuestosinternet.service.impl;

import java.io.Serializable;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.List;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mail.MailAuthenticationException;
import org.springframework.mail.MailException;
import org.springframework.mail.MailParseException;
import org.springframework.mail.MailSendException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.divemotor.ventarepuestosinternet.beans.adapter.CotizacionAdapter;
import com.divemotor.ventarepuestosinternet.beans.adapter.ElementoCotizacionAdapter;
import com.divemotor.ventarepuestosinternet.beans.form.CotizacionBeanForm;
import com.divemotor.ventarepuestosinternet.dao.CotizacionDAO;
import com.divemotor.ventarepuestosinternet.dao.ImagenRepuestoCotizacionDAO;
import com.divemotor.ventarepuestosinternet.dao.PromocionCotizacionDAO;
import com.divemotor.ventarepuestosinternet.dao.SeguimientoEstadoCotizacionDAO;
import com.divemotor.ventarepuestosinternet.dao.UsuarioClienteDAO;
import com.divemotor.ventarepuestosinternet.dao.UsuarioDAO;
import com.divemotor.ventarepuestosinternet.exception.DivemotorBusinessException;
import com.divemotor.ventarepuestosinternet.model.Cotizacion;
import com.divemotor.ventarepuestosinternet.model.EstadoCotizacion;
import com.divemotor.ventarepuestosinternet.model.ImagenRepuestoCotizacion;
import com.divemotor.ventarepuestosinternet.model.ImagenRepuestoCotizacionPK;
import com.divemotor.ventarepuestosinternet.model.Mensaje;
import com.divemotor.ventarepuestosinternet.model.PromocionCotizacion;
import com.divemotor.ventarepuestosinternet.model.PromocionCotizacionPK;
import com.divemotor.ventarepuestosinternet.model.SeguimientoEstadoCotizacion;
import com.divemotor.ventarepuestosinternet.model.SeguimientoEstadoCotizacionPK;
import com.divemotor.ventarepuestosinternet.model.Supervisor;
import com.divemotor.ventarepuestosinternet.model.Usuario;
import com.divemotor.ventarepuestosinternet.model.UsuarioCliente;
import com.divemotor.ventarepuestosinternet.model.Vendedor;
import com.divemotor.ventarepuestosinternet.service.CotizacionService;
import com.divemotor.ventarepuestosinternet.service.MensajeService;
import com.divemotor.ventarepuestosinternet.service.ServidorEmailService;
import com.divemotor.ventarepuestosinternet.service.SucursalService;
import com.divemotor.ventarepuestosinternet.service.SupervisorService;
import com.divemotor.ventarepuestosinternet.service.UsuarioClienteService;
import com.divemotor.ventarepuestosinternet.service.VendedorService;
import com.divemotor.ventarepuestosinternet.util.Constantes;
import com.divemotor.ventarepuestosinternet.util.DatosDeSession;
import com.divemotor.ventarepuestosinternet.util.FechasUtil;
import com.divemotor.ventarepuestosinternet.util.Paginacion;
				
@Service(value="cotizacionService")
@Transactional(rollbackFor=Exception.class)
public class CotizacionServiceImpl implements CotizacionService, Serializable {

	private static final long serialVersionUID = 1L;
	private static final Logger logger = Logger.getLogger(CotizacionServiceImpl.class);
	
	@Autowired
	private UsuarioClienteDAO usuarioClienteDAO;
	@Autowired
	private UsuarioDAO usuarioDAO;
	@Autowired
	private CotizacionDAO cotizacionDAO;
    @Autowired
    private SeguimientoEstadoCotizacionDAO seguimientoEstadoCotizacionDAO;
    @Autowired
    private UsuarioClienteService usuarioClienteService;
    @Autowired
    private ImagenRepuestoCotizacionDAO imagenRepuestoCotizacionDAO;
    @Autowired
    private PromocionCotizacionDAO promocionCotizacionDAO;
	@Autowired
	private SucursalService sucursalService;
	@Autowired
	private VendedorService vendedorService;
	@Autowired
	private ServidorEmailService servidorEmailService;
	@Autowired
	private MensajeService mensajeService;
	@Autowired
	private String emailAdministrador;
	@Autowired
	private SupervisorService supervisorService;

	@Override
	public void actualizarUsuarioDeCliente(UsuarioCliente usuarioCliente) throws DivemotorBusinessException {
		usuarioCliente.setUsuarioModificacion(DatosDeSession.obtenerUsuarioAutenticado());
	    usuarioCliente.setFechaModificacion(FechasUtil.obtenerFechaActual());
	    usuarioDAO.actualizar(usuarioCliente.getUsuario());
		usuarioClienteDAO.actualizar(usuarioCliente);
	}

	@Override
	@Transactional(noRollbackFor= {MailParseException.class, MailAuthenticationException.class, MailSendException.class})
	public void guardar(Cotizacion cotizacion) throws DivemotorBusinessException {
		String mail 		 = null;
		Integer idCotizacion = null;
		try {
			cotizacion.setIdCotizacion(null);
			cotizacion.setEstado(Constantes.ESTADO_ACTIVO);
			cotizacion.setUsuarioCreacion(DatosDeSession.obtenerUsuarioAutenticado());
			cotizacion.setUsuarioCliente(usuarioClienteService.obtenerUsuarioClientePorUsuario(DatosDeSession.obtenerUsuarioAutenticado()));
			cotizacion.setFechaCreacion(FechasUtil.obtenerFechaActual());
			cotizacion.setEstadoCotizacion(new EstadoCotizacion(Constantes.ID_ESTADO_COTIZACION_POR_ATENDER));
			
			Cotizacion cotizacionIngresada = cotizacionDAO.guardar(cotizacion);
			
			for (ImagenRepuestoCotizacion imagenRepuestoCotizacion : cotizacion.getListaImagenRepuestoCotizaciones()) {
				ImagenRepuestoCotizacionPK imagenRepuestoCotizacionPK=new ImagenRepuestoCotizacionPK();
				imagenRepuestoCotizacionPK.setIdCotizacion(cotizacionIngresada.getIdCotizacion());
				imagenRepuestoCotizacionPK.setIdImagenRepuesto(imagenRepuestoCotizacion.getImagenRepuesto().getIdImagenRepuesto());
				imagenRepuestoCotizacion.setIdImagenRepuestoCotizacion(imagenRepuestoCotizacionPK);
				imagenRepuestoCotizacionDAO.insertar(imagenRepuestoCotizacion);
			}
			
			for (PromocionCotizacion promocionCotizacion : cotizacion.getListaPromocionCotizaciones()) {
				PromocionCotizacionPK promocionCotizacionPK=new PromocionCotizacionPK();
				promocionCotizacionPK.setIdCotizacion(cotizacionIngresada.getIdCotizacion());
				promocionCotizacionPK.setIdPromocion(promocionCotizacion.getPromocion().getIdPromocion());
				promocionCotizacion.setIdPromocionCotizacion(promocionCotizacionPK);
				promocionCotizacion.setCotizacion(cotizacionIngresada);
				promocionCotizacionDAO.insertar(promocionCotizacion);
			}
			
			SeguimientoEstadoCotizacion seguimientoEstadoCotizacion = new SeguimientoEstadoCotizacion();
			SeguimientoEstadoCotizacionPK seguimientoEstadoCotizacionPK = new SeguimientoEstadoCotizacionPK();
			seguimientoEstadoCotizacionPK.setIdCotizacion(cotizacionIngresada.getIdCotizacion());
			seguimientoEstadoCotizacionPK.setIdEstadoCotizacion(Constantes.ID_ESTADO_COTIZACION_POR_ATENDER);
			seguimientoEstadoCotizacion.setFechaCambio(FechasUtil.obtenerFechaActual());
			seguimientoEstadoCotizacion.setSeguimientoEstadoCotizacionPK(seguimientoEstadoCotizacionPK);
			seguimientoEstadoCotizacionDAO.guardar(seguimientoEstadoCotizacion);
			
			Mensaje mensaje 	 = mensajeService.obtenerMsjPorCodigoSistemaPais();
			idCotizacion 		 = cotizacionIngresada.getIdCotizacion();
			mail				 = supervisorService.obtenerSupervisorSucursal(cotizacion.getSucursal());
			servidorEmailService.enviar(emailAdministrador, mail, MessageFormat.format(mensaje.getTituloMensaje(), idCotizacion), 
										MessageFormat.format(mensaje.getCuerpoMensaje(), idCotizacion, cotizacion.getCliente()));
		} catch (MailException ma){ 
			logger.warn(MessageFormat.format(Constantes.ERROR_MAIL, mail, idCotizacion));
		} 
	}

	@Override
	public List<CotizacionAdapter> buscarCotizacionPorUsuarioAutenticado(CotizacionBeanForm cotizacionBeanForm) throws DivemotorBusinessException {
		return cotizacionDAO.buscar(cotizacionBeanForm);
	}
	
	@Override
	public Cotizacion obtenerCotizacionPorIdConDetalle(Integer idCotizacion) throws DivemotorBusinessException{
		return cotizacionDAO.obtenerPorId(idCotizacion);
	}
	
	@Override
	public List<Cotizacion> listar() throws DivemotorBusinessException {
		return cotizacionDAO.listar();
	}

	@Override
	public List<Cotizacion> listarPorSupervisor() throws DivemotorBusinessException {
		Usuario usuario = new Usuario();
		usuario = DatosDeSession.obtenerUsuarioAutenticado();
		Supervisor supervisor = new Supervisor();
		supervisor.setUsuario(usuario);
		List<Cotizacion> listaCotizaciones = new ArrayList<Cotizacion>();
		listaCotizaciones = cotizacionDAO.listarPorSupervisor(supervisor);
		return listaCotizaciones;
	}

	@Override
	public List<EstadoCotizacion> obtenerEstadosCotizacionPorUsuarioSucursal(Usuario usuarioAutenticado) throws DivemotorBusinessException {
		return cotizacionDAO.obtenerEstadosCotizacionPorUsuarioSucursal(usuarioAutenticado);
	}

	@Override
	public List<Vendedor> obtenerVendedoresPorUsuarioSucursal(Usuario usuarioAutenticado) throws DivemotorBusinessException {
		return cotizacionDAO.obtenerVendedoresPorUsuarioSucursal( usuarioAutenticado);
	}

	@Override
	public List<CotizacionAdapter> buscarAdapter(Paginacion paginacion, CotizacionBeanForm cotizacionBean) throws DivemotorBusinessException {
		cotizacionBean.setListaSucursales(sucursalService.listarSucursalesPorPerfilAutenticado());
		return cotizacionDAO.buscarAdapter(paginacion,cotizacionBean, true);
	}

	@Override
	public int cantidadCotizaciones(CotizacionBeanForm cotizacionBean) throws DivemotorBusinessException {
		cotizacionBean.setListaSucursales(sucursalService.listarSucursalesPorPerfilAutenticado());
		return cotizacionDAO.cantidadCotizaciones(cotizacionBean, true);
	}

	@Override
	public int cantidadCotizaciones() throws DivemotorBusinessException {
		return cotizacionDAO.cantidadCotizaciones();
	}
	
	@Override
	public List<ElementoCotizacionAdapter> obtenerDetalleCotizacionAdapter(Integer idCotizacion){
		return cotizacionDAO.obtenerElementosCotizacion(idCotizacion);
	}
	
	@Override
	public List<ElementoCotizacionAdapter> obtenerDetalleRepuesto(Integer idCotizacion){
		return cotizacionDAO.obtenerDetalleRepuesto(idCotizacion);
	}
    
	@Override
    public List<ElementoCotizacionAdapter> obtenerDetallePromocion(Integer idCotizacion){
    	return cotizacionDAO.obtenerDetallePromocion(idCotizacion);
    }
	
	@Override
	public void actualizar(Integer idCotizacion, Integer idEstadoCotizacionEditar, Integer idVendedorEditar,
						   String observaciones) throws DivemotorBusinessException {
		
		Cotizacion cotizacion = new Cotizacion();
		cotizacion = cotizacionDAO.obtenerPorId(idCotizacion);
		cotizacion.setEstadoCotizacion(new EstadoCotizacion(idEstadoCotizacionEditar));
        cotizacion.setObservacion(observaciones);
        
        if (idEstadoCotizacionEditar.equals(Constantes.ID_ESTADO_COTIZACION_POR_ATENDER)) {
        	cotizacion.setVendedor(null);
		} else if (!(idVendedorEditar.equals(Constantes.NO_SELECCIONADO))) {
        	cotizacion.setVendedor(new Vendedor(idVendedorEditar));
		} else {
			throw new DivemotorBusinessException("Debe seleccionar un vendedor para este cambio de estado.");
		}
        
		cotizacion.setFechaModificacion(FechasUtil.obtenerFechaActual());
		cotizacion.setUsuarioModificacion(DatosDeSession.obtenerUsuarioAutenticado());
		
		cotizacionDAO.actualizar(cotizacion);
		
		SeguimientoEstadoCotizacion seguimientoEstadoCotizacion = new SeguimientoEstadoCotizacion();
	    SeguimientoEstadoCotizacionPK seguimientoEstadoCotizacionPK = new SeguimientoEstadoCotizacionPK();
	    seguimientoEstadoCotizacionPK.setIdCotizacion(idCotizacion);
	    seguimientoEstadoCotizacionPK.setIdEstadoCotizacion(idEstadoCotizacionEditar);
	    seguimientoEstadoCotizacion.setSeguimientoEstadoCotizacionPK(seguimientoEstadoCotizacionPK);
	    seguimientoEstadoCotizacion.setFechaCambio(FechasUtil.obtenerFechaActual());  
	    
	    seguimientoEstadoCotizacionDAO.guardar(seguimientoEstadoCotizacion);
	}

	@Override
	public List<CotizacionAdapter> buscarCotizacionesVendedor(Paginacion paginacion, CotizacionBeanForm cotizacionBean) throws DivemotorBusinessException {
		cotizacionBean.setIdVendedor(vendedorService.obtenerPorUsuario(DatosDeSession.obtenerUsuarioAutenticado()).getIdVendedor());
		cotizacionBean.setListaSucursales(sucursalService.listarSucursales());
		return cotizacionDAO.buscarVendedorAdapter(paginacion,cotizacionBean);
	}
	
	@Override
	public int cantidadCotizacionesVendedor(CotizacionBeanForm cotizacionBean) throws DivemotorBusinessException {
		//Verificar la obtencion del vendedor
		cotizacionBean.setIdVendedor(vendedorService.obtenerPorUsuario(DatosDeSession.obtenerUsuarioAutenticado()).getIdVendedor());
		cotizacionBean.setListaSucursales(sucursalService.listarSucursales());
		return cotizacionDAO.cantidadCotizaciones(cotizacionBean, false);
	}
	
	@Override
	public List<Cotizacion> listarCotizacionesDeUsuarioClienteAutenticado(Integer idUsuario) throws DivemotorBusinessException {
		return cotizacionDAO.listarPorUsuario(idUsuario);
	}

	@Override
	public void actualizar(Cotizacion cotizacionEditar) throws DivemotorBusinessException {
        Integer idEstadoCotizacion = cotizacionEditar.getEstadoCotizacion().getIdEstadoCotizacion();
        
        if (idEstadoCotizacion == Constantes.ID_ESTADO_COTIZACION_POR_ATENDER) {
        	cotizacionEditar.setVendedor(null);
		} else if (cotizacionEditar.getVendedor().getIdVendedor() == Constantes.NO_SELECCIONADO) {
			throw new DivemotorBusinessException("Debe seleccionar un vendedor para este cambio de estado.");
		}
        
        cotizacionEditar.setFechaModificacion(FechasUtil.obtenerFechaActual());
        cotizacionEditar.setUsuarioModificacion(DatosDeSession.obtenerUsuarioAutenticado());
		
		cotizacionDAO.actualizar(cotizacionEditar);
		
		SeguimientoEstadoCotizacion seguimientoEstadoCotizacion = new SeguimientoEstadoCotizacion();
	    SeguimientoEstadoCotizacionPK seguimientoEstadoCotizacionPK = new SeguimientoEstadoCotizacionPK();
	    seguimientoEstadoCotizacionPK.setIdCotizacion(cotizacionEditar.getIdCotizacion());
	    seguimientoEstadoCotizacionPK.setIdEstadoCotizacion(idEstadoCotizacion);
	    seguimientoEstadoCotizacion.setSeguimientoEstadoCotizacionPK(seguimientoEstadoCotizacionPK);
	    seguimientoEstadoCotizacion.setFechaCambio(FechasUtil.obtenerFechaActual());  
	    
	    seguimientoEstadoCotizacionDAO.guardar(seguimientoEstadoCotizacion);
		
	}

}
